<script lang="ts" setup>
import type { DiffStats, FoldingConfig } from '@/utils/diffUtils'
import Codemirror from 'codemirror-editor-vue3'

import { computed, reactive, ref } from 'vue'
import {
  compareDiff,
  copyResult,
  toggleFold,
} from '@/utils/diffUtils'
// placeholder
import 'codemirror/addon/display/placeholder.js'
// language
import 'codemirror/mode/javascript/javascript.js'
// theme
import 'codemirror/theme/dracula.css'

const leftText = ref('')
const rightText = ref('')
const diffResult = ref<string[]>([])
const diffMode = ref<'chars' | 'words' | 'lines'>('lines')

const cmOptions = {
  mode: 'javascript',
  theme: 'dracula',
  lineNumbers: true,
  lineWrapping: true,
  placeholder: '输入对比文本',
}

// 差异统计
const diffStats = reactive<DiffStats>({
  added: 0,
  removed: 0,
  total: 0,
})

// 折叠相同行的配置
const foldingConfig = reactive<FoldingConfig>({
  enabled: true,
  threshold: 3,
  expandedSections: new Set<string>(),
})

// 计算HTML结果
const diffHtml = computed(() => {
  return diffResult.value.join('')
})

// 清空所有内容
function clearAll() {
  leftText.value = ''
  rightText.value = ''
  diffResult.value = []
}

// 交换左右文本
function swapTexts() {
  const temp = leftText.value
  leftText.value = rightText.value
  rightText.value = temp

  // 如果已经有比较结果，则重新比较
  if (diffResult.value.length > 0) {
    doCompareDiff()
  }
}

// 比较差异
function doCompareDiff() {
  diffResult.value = compareDiff(
    leftText.value,
    rightText.value,
    diffMode.value,
    foldingConfig,
    diffStats,
  )
}

// 全局暴露toggleFold函数，以便在HTML中调用
if (typeof window !== 'undefined') {
  (window as any).toggleFold = (sectionId: string) => {
    toggleFold(sectionId, foldingConfig)
  }
}

// 复制结果的包装函数
function doCopyResult() {
  copyResult(diffResult.value)
}
</script>

<template>
  <div class="mx-auto p-6">
    <div class="flex flex-col space-y-6">
      <!-- 输入区域 -->
      <div class="flex flex-col gap-4 md:flex-row">
        <div class="w-full md:w-1/2">
          <div class="mb-2 flex items-center">
            <span class="text-gray-700 font-medium">对比文本-左</span>
            <div class="ml-auto text-xs text-gray-500">
              {{ leftText.length }} 个字符
            </div>
          </div>
          <Codemirror v-model:value="leftText" :options="cmOptions" border placeholder="输入对比文本A" :height="400" />
        </div>
        <div class="w-full md:w-1/2">
          <div class="mb-2 flex items-center">
            <span class="text-gray-700 font-medium">对比文本-右</span>
            <div class="ml-auto text-xs text-gray-500">
              {{ rightText.length }} 个字符
            </div>
          </div>
          <Codemirror v-model:value="rightText" :options="cmOptions" border placeholder="输入对比文本B" :height="400" />
        </div>
      </div>

      <!-- 操作按钮 -->
      <div class="flex flex-wrap justify-center gap-4">
        <button
          class="flex items-center gap-2 rounded-lg bg-blue-600 px-6 py-2.5 text-white shadow-sm transition-colors hover:bg-blue-700"
          @click="doCompareDiff"
        >
          <i class="el-icon-view" />对比文本
        </button>
        <button
          class="flex items-center gap-2 rounded-lg bg-gray-600 px-6 py-2.5 text-white shadow-sm transition-colors hover:bg-gray-700"
          @click="swapTexts"
        >
          <i class="el-icon-refresh" />交换文本
        </button>
        <button
          class="flex items-center gap-2 rounded-lg bg-red-600 px-6 py-2.5 text-white shadow-sm transition-colors hover:bg-red-700"
          @click="clearAll"
        >
          <i class="el-icon-delete" />清空
        </button>
      </div>

      <!-- 对比结果 -->
      <div v-if="diffResult.length > 0" class="mt-6 overflow-hidden border border-gray-200 rounded-lg bg-white shadow-sm">
        <div class="flex flex-wrap items-center justify-between border-b border-gray-200 bg-gray-50 p-4">
          <div class="flex items-center">
            <h3 class="text-lg text-gray-800 font-medium">
              对比结果
            </h3>

            <!-- 差异统计信息 -->
            <div class="ml-4 flex items-center gap-3">
              <span class="diff-stat-item added">
                <span class="diff-stat-icon">+</span>
                <span class="diff-stat-value">{{ diffStats.added }}</span>
                <span class="diff-stat-label">添加</span>
              </span>
              <span class="diff-stat-item removed">
                <span class="diff-stat-icon">-</span>
                <span class="diff-stat-value">{{ diffStats.removed }}</span>
                <span class="diff-stat-label">删除</span>
              </span>
              <span class="diff-stat-item total">
                <span class="diff-stat-value">{{ diffStats.total }}</span>
                <span class="diff-stat-label">总计</span>
              </span>
            </div>
          </div>

          <div class="mt-2 flex items-center gap-2 sm:mt-0">
            <button
              class="flex items-center gap-2 rounded-lg bg-green-600 px-4 py-2 text-white shadow-sm transition-colors hover:bg-green-700"
              @click="doCopyResult"
            >
              <i class="el-icon-document-copy" />复制结果
            </button>
          </div>
        </div>
        <div
          class="diff-result overflow-x-auto bg-white p-5 font-mono"
          v-html="diffHtml"
        />
      </div>
    </div>
  </div>
</template>

<style scoped>
.diff-result {
  overflow-x: auto;
  font-size: 0.95rem;
  line-height: 1.2;
}

/* 差异块样式 */
.diff-result :deep(.diff-block) {
  margin: 0.1rem 0;
  overflow: hidden;
  border-radius: 4px;
}

.diff-result :deep(.diff-added-block) {
  background-color: rgb(74 194 107 / 5%);
  border-left: 3px solid rgb(74 194 107 / 70%);
}

.diff-result :deep(.diff-removed-block) {
  background-color: rgb(229 83 75 / 5%);
  border-left: 3px solid rgb(229 83 75 / 70%);
}

.diff-result :deep(.diff-equal-block) {
  border-left: 3px solid transparent;
}

/* 行样式 */
.diff-result :deep(.diff-line) {
  position: relative;
  display: flex;
  align-items: flex-start;
  min-height: 1.4em;
  padding: 0.08rem 0;
  word-break: break-all;
  overflow-wrap: break-word;
}

.diff-result :deep(.diff-line:hover) {
  background-color: rgb(0 0 0 / 3%);
}

/* 行号样式 */
.diff-result :deep(.line-number) {
  min-width: 2.5rem;
  padding: 0 0.4rem;
  margin-right: 0.5rem;
  font-family: monospace;
  font-size: 0.85rem;
  color: #6e7781;
  text-align: right;
  user-select: none;
  border-right: 1px solid #e1e4e8;
}

/* 差异标记 */
.diff-result :deep(.diff-marker) {
  display: inline-flex;
  align-items: center;
  margin-right: 0.3rem;
}

.diff-result :deep(.diff-icon) {
  stroke: currentcolor;
}

/* 差异内容样式 */
.diff-result :deep(.diff-added) {
  position: relative;
  display: inline;
  padding: 0 1px;
  color: #24292f;
  white-space: pre-line;
  background-color: rgb(74 194 107 / 15%);
  border-radius: 2px;
  transition: background-color 0.2s;
}

.diff-result :deep(.diff-removed) {
  position: relative;
  display: inline;
  padding: 0 1px;
  color: #24292f;
  background-color: rgb(229 83 75 / 15%);
  border-radius: 2px;
  transition: background-color 0.2s;
}

.diff-result :deep(.diff-equal) {
  display: inline;
  padding: 0 1px;
  color: #24292f;
}

/* 折叠部分样式 */
.diff-result :deep(.folded-section) {
  padding: 0.3rem 0;
  margin: 0.25rem 0;
  text-align: center;
  background-color: #f8f9fa;
  border-top: 1px dashed #e1e4e8;
  border-bottom: 1px dashed #e1e4e8;
}

.diff-result :deep(.fold-toggle) {
  display: inline-flex;
  gap: 6px;
  align-items: center;
  padding: 4px 16px;
  font-size: 12px;
  color: #57606a;
  cursor: pointer;
  background-color: #f5f5f5;
  border: 1px solid #e0e0e0;
  border-radius: 20px;
  box-shadow: 0 1px 2px rgb(0 0 0 / 5%);
  transition: all 0.2s ease;
}

.diff-result :deep(.fold-toggle:hover) {
  background-color: #e8e8e8;
  box-shadow: 0 2px 4px rgb(0 0 0 / 10%);
}

.diff-result :deep(.fold-icon) {
  transition: transform 0.3s ease;
}

.diff-result :deep(.folded-content) {
  margin-top: 0.75rem;
  animation: fadeIn 0.3s ease;
}

@keyframes fade-in {
  from {
    opacity: 0;
    transform: translateY(-5px);
  }

  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* 差异统计样式 */
.diff-stat-item {
  display: inline-flex;
  gap: 0.25rem;
  align-items: center;
  padding: 0.25rem 0.5rem;
  font-size: 0.85rem;
  background-color: #f5f5f5;
  border-radius: 1rem;
}

.diff-stat-item.added {
  color: #1a7f37;
  background-color: rgb(74 194 107 / 15%);
}

.diff-stat-item.removed {
  color: #cf222e;
  background-color: rgb(229 83 75 / 15%);
}

.diff-stat-item.total {
  color: #0969da;
  background-color: rgb(84 174 255 / 15%);
}

.diff-stat-icon {
  font-size: 1rem;
  font-weight: bold;
}

.diff-stat-value {
  font-weight: 600;
}

.diff-stat-label {
  font-size: 0.75rem;
  opacity: 0.8;
}

/* 响应式调整 */
@media (width <= 768px) {
  .diff-result {
    font-size: 0.85rem;
    line-height: 1.3;
  }

  .diff-result :deep(.line-number) {
    min-width: 1.8rem;
    padding: 0 0.2rem;
    margin-right: 0.3rem;
  }

  .diff-result :deep(.diff-line) {
    padding: 0.05rem 0;
  }

  .diff-stat-item {
    padding: 0.2rem 0.4rem;
    font-size: 0.75rem;
  }
}
</style>
